/**
 * demo6
 */
class Demo6 {
    identity(arg: number): number {
        return arg;
    }
    // 我们可以定义参数的类型来控制调用该函数时传递的参数类型
    identity1<T>(arg: T): T {
        return arg;
    }
    // 注意到我们在定义泛型时尖括号中定义的关键字是随意的，不过在前后需要一致
    toTest<A>(test: A) {
        return test;
    }
    test() {
        // 在定义mytest属性时，使用对象结构操作来定义其中的函数泛型
        let mytest: { <A>(test: A): A } = this.identity1;
        return mytest;
    }
    test1() {
        // 定义以接口的形式来定义泛型数据类型
        let test: Itest = this.identity1;
        return test;
    }
}
// 使用这种类泛型时，我们没有约束使用什么类型，只是在使用它时为什么类型就是什么类型
class Test1<T>{
    zero: T;
    add: (x: T, y: T) => T;
    // 这里我们队T进行了约束，传递的参数中务必拥有length属性
    test<T extends Ilength>(arg: T) {
        return arg.length;
    }
    // 对参数的对象类型约束
    testO<T, K extends keyof T>(obj: T, key: K): T[K] {
        return obj[key];
    }
    // 传入参数限制约束为构造类类型
    testC<T>(c: { new(): T }): T {
        return new c();
    }
}
interface Ilength {
    length: number;
}
interface Itest {
    <A>(test: A): A;
}
// 使用枚举
// 在使用该枚举时，得到的是数字，或是我们可以在定义枚举的时候去指定其值，默认从0开始，当然你也可以在定义时指定开始值
enum Color {
    Yellow,
    // Yellow = 2,此时下面将从2开始自增
    White = 'white',
    Black = 'black',
    Red = 3,
    Gray,
    // 定义其数据时也是可以使用字符串的，当其使用字符串后，后面的属性也都得使用字符串来表示。但使用字符串后，下文再次使用数字时，该次需要重新计算自增基数
}
interface Ibase {
    color: Color;
}
// implements 实现
class Bcolor implements Ibase {
    color: Color = Color.Black;
    getColor() {
        return this.color;
    }
}
let d6 = new Demo6();
let i = d6.identity1(12);
// 输出值，返回值类型为传递的值的类型
console.log(i, typeof i); //12 'number'
let i1 = d6.identity1('12');
console.log(i1, typeof i1); //12 string
// 我们在调用时，同样可以在调用时指定传递类型，所属类型用尖括号引用，然后在后期传递参数就务必使用当前指定的类型
let i2 = d6.identity1<boolean>(false);
console.log(i2, typeof i2); // false 'boolean'
let i3 = d6.test();
let r = i3('zhansan')
console.log(r, typeof r); //zhansan string
let t = d6.test1();
let r1 = t(true);
console.log(r1, typeof r1); //true 'boolean'
// 类泛型
let tt = new Test1<number>();
// 由于上面泛型类中的规定该属性类型，故而当前属性赋值时只能是该类型，当期赋值为其他类型时编辑器报错
tt.zero = 2;
console.log(tt.zero);
let tt1 = new Test1<string>();//当我们实例化时传递的是string类型，其下面调用的属性中的类型也务必是string类型
tt1.zero = 'string';
console.log(tt1.test({ length: 3 })); // 3

let xo = { a: 1, b: 2, c: 3 };
console.log(tt.testO(xo, 'a')); // 1
;
function con() {
    return 'constructor'
}
class Re {
    str: string = 'hello world';
}
console.log(tt.testC(Re).str); // hello world
let bc = new Bcolor();
// 枚举的获取，注意获取到的不是字符串，而是数字（默认情况）
console.log(bc.getColor());//2








